/*
 Authors: ZhangXuelian
 	
 
 Changes:
 	
	
*/


#include <time.h>
#include <signal.h>
#include <sys/wait.h>
#include <errno.h>
#include <assert.h>
#include <ctype.h>
#include <stdarg.h>
#include <arpa/inet.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/uio.h>
#include <sys/un.h>
#include <limits.h>
#include <float.h>
#include <math.h>
#include <sys/resource.h>
#include <sys/utsname.h>
#include <locale.h>
#include <sys/socket.h>

#include "coe_lib.h"

// 添加与硬件平台相关的平台适配层
#ifdef __LINUX_NVRAM__
  #include "osadapter_nvram.c"
#else
	#ifdef __LINUX_FILE__  
		pthread_mutex_t mutex;
		#include "osadapter_file.c"
	#endif
#endif

/**
 * 登录完成的通知，errcode为0表示登录成功，其余请参考全局的错误码表
 */
void on_login_complete(int errcode) 
{
    printf("on_login_complete | code[%d]\n", errcode);
}

/**
 * 在线状态变化通知， 状态（status）取值为 11 表示 在线， 取值为 21 表示  离线
 * old是前一个状态，new是变化后的状态（当前）
 */
void on_online_status(int old, int new_status) 
{
	printf("online status: %s\n", 11 == new_status ? "true" : "false"); 
}

/**
 * 辅助函数：SDK的log输出回调
 * SDK内部调用改log输出函数，有助于开发者调试程序
 */
#define SDK_DEBUG_INFO		1
#define SDK_DEBUG_KEYINFO	2
#define SDK_DEBUG_WARNING	3
#define SDK_DEBUG_ERROR	    4
#define SDK_DEBUG_LEVEL     SDK_DEBUG_INFO
void log_func(int level, const char* module, int line, const char* message)
{
	if(level >= SDK_DEBUG_LEVEL)
	{
		printf("module:%s - line[%d] - %s\n",module,line, message);
	}
}

void on_record_notify(char * json)
{
	
	return;
}

void on_receive_cmd(int task_no, char * json)
{
	
	return;
}

void on_cmd_sent_result(int task_no, int result)
{
	
	return;
}

/****************************************************************
*  测试代码：
*
*  （1）while循环的作用仅仅是使 Demo进程不会退出，实际使用SDK时一般不需要
*  （2） 输入 "exit" 将会退出当前进程，这段逻辑存在的原因在于：
*     					在某些芯片上，直接用Ctrl+C 退出易产生僵尸进程
*  （3）while循环里面的sleep(1)在这里是必须的，因为如果Demo进程后台运行，
*   scanf没有阻塞作用，会导致当前线程跑满CPU
*
*****************************************************************/

// 一般地，coe_lib会是设备厂商的一个程序的结构体成员。
COE_LIB coe_lib;


void start_coe(void)
{
	// load manufacturer_license
	unsigned char manufacturer_license[256] = {0};
	int nLicenseSize = 0;
	if (!read_buffer("./manufacturer_license.txt", manufacturer_license, sizeof(manufacturer_license), &nLicenseSize)) 
	{
		printf("[error]get license from file failed...\n");
		return false;
	}

	// load device_serial_number_license
	unsigned char device_serial_number_license[32] = {0};
	int sn_size = 0;
	if(!read_buffer("./device_serial_number_license.txt", device_serial_number_license, sizeof(device_serial_number_license), &sn_size)) 
	{
		printf("[error]get guid from file failed...\n");
		return false;
	}

	// 设备的基本信息
	memset(&coe_lib.device_info,0,sizeof(COE_DEVICE_INFO));
	coe_lib.device_info.os_platform = "linux";
	// 厂商信息
	coe_lib.device_info.manufacturer_id = "我是一个厂商ID";
	coe_lib.device_info.manufacturer_license = manufacturer_license;
	// 产品信息
	coe_lib.device_info.product_id = 10001;
	coe_lib.device_info.product_version = 1;
	// 设备本身信息
	coe_lib.device_info.device_name = "demo1";
	coe_lib.device_info.device_serial_number = "我是一个SN号";
	coe_lib.device_info.device_serial_number_license = device_serial_number_license;
	coe_lib.device_info.sdk_type = 1;
	coe_lib.device_info.test_mode = 1;     

	// 设备登录、在线状态、指令消息等相关的事件通知
	// 注意事项：
	// 如下的这些notify回调函数，都是来自硬件SDK内部的一个线程，所以在这些回调函数内部的代码一定要注意线程安全问题
	// 比如在on_login_complete操作某个全局变量时，一定要考虑是不是您自己的线程也有可能操作这个变量
	coe_lib.device_notify.on_online_status  = on_online_status;
	coe_lib.device_notify.on_login_complete  = on_login_complete;

	coe_lib.device_data_fun.write = coe_write; 
	coe_lib.device_data_fun.read = coe_read;
	coe_lib.device_data_fun.delete = coe_delete;	

	coe_lib.log_func = log_func;
	if ( !initDevice(&coe_lib) ) 
	{
		return -1;
	}

	coe_lib.cmd_handler = initDeviceCmd(on_receive_cmd, on_cmd_sent_result);
	coe_lib.record_handler = initDeviceRecord(on_record_notify);

}


void stop_coe(void)
{
	deinitDevice();
}


int main(int argc, char **argv) 
{
#ifdef __LINUX_FILE__
	pthread_mutex_init(&mutex, NULL);
#endif

	start_coe();
	// user do something.

	// 可以在任何一个引入 coe_lib.h 文件的地方调用以下代码。
	
	// 1\发送指令的结果给服务器。
	// 2\发送新的指令给服务器，也是这个指令。
	coe_lib.cmd_handler->cmd_send(time(NULL),"",1);
	
	// 发送采集记录给服务器。

	coe_lib.record_handler->record_send("json",3,0,1);
	

	char input[10] = {0};
	while (scanf("%s", input)) 
    {
		if ( !strcmp(input, "exit") ) 
        {
			deinitDevice();
			break;
		}
		sleep(1);
	}
#ifdef __LINUX_FILE__
	pthread_mutex_destroy(&mutex);
#endif
	return 0;
}

/* The End */
